var Routes = {
	INTERNAL : {
		path: document.location.pathname,	// qui dovrei utilizzare la root
		definedRoutes: [],
	},
	useHistory: true
};

Routes.start = function(){
	
	if(Routes.useHistory == true && history && history.pushState){
		 window.onpopstate = function(){
			 Routes.INTERNAL.checkRoute(document.location.pathname);
		 }
		 
    } else {
    	var fn = function(){ 
    		var completeUrl = location.hash.substring(1);
    		Routes.INTERNAL.checkRoute(completeUrl);
    	}
    	
    	if ("onhashchange" in window && (!document.documentMode || document.documentMode >= 8)) {
    		window.onhashchange = fn;
        } else {
            setInterval(fn, 50);
        }
        
    }
	

	if (Routes.useHistory == true && history && history.pushState) {
		Routes.INTERNAL.checkRoute(document.location.pathname);
	
	} else {
		var completeUrl = location.hash.substring(1);
		if(completeUrl == ''){
			// if hash is null check path
			Routes.INTERNAL.checkRoute(document.location.pathname);
		} else {
			Routes.INTERNAL.checkRoute(completeUrl);	
		}
		
	}
	
}

Routes.add = function(url, callback){
	Routes.INTERNAL.definedRoutes.push({
		// qui dovrei utilizzare la root
		matcher: Routes.INTERNAL.createMatcher(url),
		callback: callback
	});
}

Routes.navigate = function(url){
	
	Routes.INTERNAL.checkRoute(url);
	
	if(Routes.useHistory == true && history && history.pushState){
		history.pushState({}, url, url);
	} else {
    	window.location.hash = "#" + url;
    }
}
Routes.INTERNAL.checkRoute = function(completeUrl){
	 var routeAndTokens = Routes.INTERNAL.getRoute(completeUrl);
	 routeAndTokens.route.callback(routeAndTokens.tokens);
}
Routes.INTERNAL.getRoute = function(completeUrl){
	for(var i = 0; i < Routes.INTERNAL.definedRoutes.length; i++){
		var tokens = Routes.INTERNAL.definedRoutes[i].matcher(completeUrl); 
		if(tokens != null){
			return {
				tokens: tokens,
				route: Routes.INTERNAL.definedRoutes[i]
			}
		}
	}
	throw new Error('Ivalid route: ' + completeUrl);
}
Routes.INTERNAL.createMatcher = function(matcher){
	return function(url){
		//alert('check: ' + matcher);
		var tokens = {};
		
		var splittedUrl = url.split('/');
		var splittedMatcher = matcher.split('/');
		//alert('JSON: ' + JSON.stringify(splittedMatcher));
		//alert('JSON: ' + JSON.stringify(splittedUrl));
		
		
		
		if(splittedUrl.length == splittedMatcher.length){
			for(var i = 0; i < splittedUrl.length; i++){
				//alert(i + ' - ' +splittedMatcher[i]);
				if(splittedMatcher[i].charAt(0) == '{') {
					tokens[splittedMatcher[i].substring(1, splittedMatcher[i].length - 1)] = splittedUrl[i];
					continue;
				} else {
					if(splittedMatcher[i] != splittedUrl[i]) return null;
				}
			}
			//alert(JSON.stringify(splittedMatcher));
			//alert(JSON.stringify(tokens));
			//alert(true);
			return tokens;
		}
		
		return null;
	};
}
/*
Routes.INTERNAL.createMatcher = function(url){
	var matchers = [];
	var token = null;
	var tokenType = Routes.INTERNAL.tokens.WORD;
	
	for(var pi = 0; pi < value.length; pi++){
		
		var currentChar = value.charAt(pi);
		
		if(currentChar == '{'){
			Routes.INTERNAL.collectToken(matchers, tokenType, token);
			tokenType = Routes.INTERNAL.tokens.GROUP;
			
			continue;
		}
		if(currentChar == '}'){
			Routes.INTERNAL.collectToken(matchers, tokenType, token);
			tokenType = Routes.INTERNAL.tokens.WORD;
			continue;
		}
		
		if(token == null) token = '';
		token += currentChar;
	}
	
	return function(url){
		
	}
}
Routes.INTERNAL.collectToken = function(matchers, tokenType, token){
	if(token != null) {
		if(tokenType == Routes.INTERNAL.tokens.WORD) matchers.push(Routes.INTERNAL.wordMatcher(token));
		if(tokenType == Routes.INTERNAL.tokens.GROUP) matchers.push(Routes.INTERNAL.groupMatcher(token));
		
	}
}
Routes.INTERNAL.wordMatcher = function(word){
	return function(token){
		
		return token == word;
	}
}
Routes.INTERNAL.groupMatcher = function(word){
	return function(token){
		return true;
	}
}
*/